package br.ufcg.edu.descompressao;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import br.ufcg.edu.algoritimo.DecodificadorHuffman;
import br.ufcg.edu.algoritimo.Huffman;
import br.ufcg.edu.algoritimo.No;
import br.ufcg.edu.util.Constantes;

public class Descompressao implements DescompIF {

	private InputStream inputStream;
	private OutputStream outputStream;

	public Descompressao(InputStream inputStream, OutputStream outputStream) {
		this.inputStream = inputStream;
		this.outputStream = outputStream;
	}

	private void lerBits(DataInputStream reader, No<Long> no)
			throws IOException {
		int bitsRestantes = reader.readInt();
		DecodificadorHuffman decodificador = new DecodificadorHuffman(no);
		DataOutputStream writer = geraArquivoSaida();

		try {
			while (bitsRestantes > 0) {
				int valorSequencia = reader.readChar();
				int valorTruncar = Math.min(
						Constantes.NUMERO_DE_BITS_DE_CARACTER, bitsRestantes);
				String sequencia = preencherEspacoSequencia(
						Integer.toString(valorSequencia, 2)).substring(0,
						valorTruncar);
				salvaEmArquivo(writer,
						decodificador.decodificaCaracteres(sequencia
								.toCharArray()));
				bitsRestantes -= valorTruncar;
			}
		} finally {
			writer.close();
		}
	}

	private void salvaEmArquivo(DataOutputStream writer,
			String decodificaCaracteres) throws IOException {
		for (int caracter : decodificaCaracteres.toCharArray()) {
			writer.writeByte(caracter);
		}
	}

	private DataOutputStream geraArquivoSaida() throws IOException {
		DataOutputStream writer = new DataOutputStream(
				new BufferedOutputStream(this.outputStream));
		return writer;
	}

	private String preencherEspacoSequencia(String sequencia) {
		StringBuilder saida = new StringBuilder();
		int valorCompletar = Constantes.NUMERO_DE_BITS_DE_CARACTER
				- sequencia.length();
		for (int i = 0; i < valorCompletar; i++) {
			saida.append(Constantes.BIT_ZERO);
		}
		saida.append(sequencia);

		return saida.toString();

	}

	public static void main(String[] args) throws IOException {
		Descompressao desc = new Descompressao(System.in, System.out);
		desc.start();
	}

	@Override
	public void start() throws IOException {
		DataInputStream reader = new DataInputStream(new BufferedInputStream(
				this.inputStream));
		int numero_de_caracteres = reader.readByte();
		List<No<Long>> nos = new ArrayList<No<Long>>();
		for (int i = 0; i < numero_de_caracteres; i++) {
			int caracter = reader.readByte();
			long ocorrencia = reader.readLong();
			nos.add(new No<Long>(null, null, ocorrencia, caracter, true));
		}

		Huffman huffman = new Huffman();
		No<Long> no = huffman.construirArvore(huffman
				.construirListaOrdenadaDeNos(nos));
		lerBits(reader, no);

		
	}

}
